#!/usr/bin/env python
# encoding: utf-8
"""
DatabaseController.py

Created by Pablo Ortega Mesa on 2011-01-28.
Copyright (c) 2011 Toeska Research Group. All rights reserved.
"""

import MySQLdb
import os
import re
import getopt
import sys
class Lattice():
	def __init__(self,lattice):
		self.lattice = lattice
		self.readLattice()

	def readLattice(self):
		f = open(self.lattice,"r")
		__lineN = 3
		counter = 0
		nodos = []
		nodo = {}
		for line in f:
			if not (line.startswith("#") or line.startswith("Top") or line.startswith("Bottom") or line.startswith("\n") or "generators" in line):
				counter += 1
				if counter%__lineN==1: #terms, docs stability and level information
					extent = line[line.index("[")+1:line.index("]")]
					nodo["extent"] = extent.split(", ")
					intent = line[line.index("{")+1:line.index("}")]
					nodo["intent"] = intent.split(", ")
					id = line[line.index("id=")+3:line.index("type")].replace(", ","")
					nodo["id"] = id
					lev = line[line.index("level=")+6:line.index("stability")].replace(", ","")
					nodo["level"] = lev
					stab = line[line.rfind("=")+1:]
					stab = float(stab.replace("]\n",""))
					nodo["stability"] = stab
					nodo["support"] = line[line.index("(")+1:line.index(")")]
					#[o2, o3, o4, o5] x {c} (4) [id=8, type=inner, level=1, stability=0.25]
				if counter%__lineN==2: #parents
					parent = line[line.index("[")+1:line.index("]")]
					parent = parent.split("}, ")
					padres = []
					for c in range(len(parent)):
						par = parent[c].replace("{","").replace("}","").strip()
						if par == "":
							padres.append("none")
						else:
							padres.append(par)
					if padres:
						nodo["parents"] = padres
				if counter%__lineN==0: #childrens
					children = line[line.index("[")+1:line.index("]")]
					children = children.split("}, ")
					hijos = []
					for c in range(len(children)):
						hij = children[c].replace("{","").replace("}","").strip()
						if hij == "":
							hijos.append("none")
						else:
							hijos.append(hij)
					if hijos:
						nodo["childrens"] = hijos
					
					if (nodo["extent"][0]!='') and (nodo["intent"][0]!='') and nodo["level"] and nodo["stability"] and nodo["id"] and nodo["parents"] and nodo["childrens"] and nodo["support"]:
						nodos.append(nodo)
					nodo = {}
		self.nodos = nodos
	
	def __readTerms(self,filename):
		terms = []
		fterms = open(filename,"r")
		for line in fterms:
			term = line.split("\t")[0]
			if term!='':
				terms.append(term)
		print str(len(terms))+" terms read"
		return terms
	
	def __readDocs(self,path):
		docs = []
		posibles = os.listdir(path)
		for f in posibles:
			if re.search('(txt)$',f):
				docs.append(path+f)
		print str(len(docs))+" docs listed"
		return docs
	
	def __insert_tableLattice(self,latticeName,docs,terms,intent="docs"):
		if intent == "docs":
			intentSize = len(docs)
			extentSize = len(terms)
		else:
			intentSize = len(terms)
			extentSize = len(docs)
		query = 'INSERT INTO Lattice(conceptSize,intentSize,extentSize,name) VALUES('+str(len(self.nodos))+','+str(intentSize)+','+str(extentSize)+',"'+latticeName+'")'
		self.cursor.execute(query)
		self.plainSql += query+"\n"
		querySelect = "SELECT id FROM Lattice WHERE conceptSize="+str(len(self.nodos))+" AND intentSize="+str(intentSize)+" AND extentSize="+str(extentSize)+" AND name=\""+latticeName+"\" ORDER BY id DESC"
		self.cursor.execute(querySelect)
		resultado=self.cursor.fetchone()
		
		return resultado[0]
	
	def __insert_tableEntity(self,idLattice,docs,terms):
		#Insert terms
		for term in terms:
			sql = "INSERT INTO Entity(value,type,idLattice) VALUES(\""+term+"\",2,"+str(idLattice)+")"
			self.plainSql += sql+"\n"
			self.cursor.execute(sql)
		#Insert docs
		for doc in docs:
			sql = "INSERT INTO Entity(value,type,idLattice) VALUES(\""+doc+"\",1,"+str(idLattice)+")"
			self.plainSql += sql+"\n"
			self.cursor.execute(sql)
	
	def __select_tableEntity(self,type,value):
		sql = "SELECT id FROM Entity WHERE type="+str(type)+" AND value=\""+value+"\" LIMIT 1"
		self.cursor.execute(sql)
		resultado = self.cursor.fetchone()
		if resultado!=None:
			return resultado[0]
		else:
			return None
	
	def __insert_tableConcept(self,idLattice):
		for nodo in self.nodos:
			sql = "INSERT INTO Concept(stab,support,level,idLattice,number) VALUES("+str(nodo['stability'])+","+str(nodo['support'])+","+str(nodo['level'])+","+str(idLattice)+","+str(nodo['id'])+")"
			self.cursor.execute(sql)
			self.plainSql += sql+"\n"
			print "Seleccionando concepto con number="+str(nodo['id'])
			querySelect = "SELECT id FROM Concept WHERE stab="+str(nodo['stability'])+" AND support="+str(nodo['support'])+" AND level="+str(nodo['level'])+" AND idLattice="+str(idLattice)+" AND number="+str(nodo['id'])+" ORDER BY id DESC"
			self.cursor.execute(querySelect)
			resultado = self.cursor.fetchone()
			if resultado!= None:
				idConcept = resultado[0]
				for intentElement in nodo['intent']:
					idEntity = self.__select_tableEntity(2,intentElement)
					sql =  "INSERT INTO IntentExtent(idConcept,idEntity,type) VALUES("+str(idConcept)+","+str(idEntity)+",1)"
					self.cursor.execute(sql)
					self.plainSql += sql+"\n"
				for extentElement in nodo['extent']:
					idEntity = self.__select_tableEntity(1,extentElement)
					sql =  "INSERT INTO IntentExtent(idConcept,idEntity,type) VALUES("+str(idConcept)+","+str(idEntity)+",2)"
					self.cursor.execute(sql)
					self.plainSql+="\n"
				for parentEntity in nodo['parents']:
					if parentEntity != 'none':
						idEntity = self.__select_tableEntity(2,parentEntity)
						sql = "INSERT INTO Relation(type,idEntity,idConcept) VALUES(1,"+str(idEntity)+","+str(idConcept)+")"
						self.cursor.execute(sql)
						self.plainSql += sql+"\n"
	
				childrens =  nodo['childrens'][0].split(", ")
				for childrenEntity in childrens:
					if childrenEntity != 'none':
						idEntity = self.__select_tableEntity(2,childrenEntity)
						sql = "INSERT INTO Relation(type,idEntity,idConcept) VALUES(2,"+str(idEntity)+","+str(idConcept)+")"
						self.cursor.execute(sql)
						self.plainSql += sql+"\n"
	
	def __readContext(self,filename):
		contextFile = open(filename,'r')
		cont = 0
		for line in contextFile:
			cont += 1
			if cont == 5:
				extent = line.split("\n")[0].split(" | ")
				extent = extent[:-1]
			if cont == 6:
				intent = line.split("\n")[0].split(" | ")
				intent = intent[:-1]
		return intent,extent
	
	def parseMySql(self,latticeName,contextFilename,intent="docs"):
		terms,docs = self.__readContext(contextFilename)
		self.plainSql = ''
		db=MySQLdb.connect(host='localhost',user='lattice',passwd='lattice',db='Lattices')
		self.cursor=db.cursor()
		idLattice = self.__insert_tableLattice(latticeName,docs,terms,intent)
		print "Id Lattice: "+str(idLattice)
		self.__insert_tableEntity(idLattice,docs,terms)
		self.__insert_tableConcept(idLattice)
		db.commit()
		fplainSql = open(latticeName+".sql","w")
		fplainSql.write(self.plainSql)
		fplainSql.close()
							


options, remainder = getopt.getopt(sys.argv[1:],'c:l:n:',['context=',
														'lattice=',
														'name='])											


latticeFilename = False
context = False
name = False			
for opt,arg in options:
	if opt in ('-c','--context'):
		context = arg
	if opt in ('-l','--lattice'):
		latticeFilename = arg
	if opt in ('-n','--name'):
		name = arg

if not latticeFilename or not context or not name:
	print "USAGE python "+sys.argv[0]+" --context contextFilename.rcf --lattice latticeFilename.lat --name NameOfLattice"
	exit(0)
lattice = Lattice(latticeFilename)
#lattice.parseMySql(name,context)
